package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.dto.ReservationDto;
import com.zzyl.entity.Elder;
import com.zzyl.entity.Reservation;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.ElderMapper;
import com.zzyl.mapper.ReservationMapper;
import com.zzyl.service.ReservationService;
import com.zzyl.utils.MobThreadLocal;
import com.zzyl.vo.ReservationVo;
import com.zzyl.vo.TimeCountVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
@Transactional
public class ReservationServiceImpl implements ReservationService {

    @Autowired
    private ReservationMapper reservationMapper;
    @Autowired
    private ElderMapper elderMapper;

    /**
     * 分页查找预约
     *
     * @param page   页码
     * @param size   每页大小
     * @param name   预约人姓名
     * @param phone  预约人手机号
     * @param status 预约状态
     * @param type   预约类型
     * @return 预约列表
     */
    @Override
    public PageResponse<ReservationVo> findByPage(int page, int size, String name, String phone, Integer status, Integer type, LocalDateTime startTime, LocalDateTime endTime) {
        PageHelper.startPage(page, size);
        Long userId = MobThreadLocal.getUserId();
        Page<Reservation> byPage = reservationMapper.findByPage(page, size, name, phone, status, type, userId, startTime, endTime);
        return PageResponse.of(byPage, ReservationVo.class);
    }

    /**
     * 查询取消预约数量
     */
    @Override
    public Integer cancelReservationConut() {
        Long userId = MobThreadLocal.getUserId();

        DateTime startTime = DateUtil.beginOfDay(new Date());
        long time = startTime.getTime();
        Instant instant = Instant.ofEpochMilli(time);
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localStartTime = instant.atZone(zoneId).toLocalDateTime();

        DateTime endTime = DateUtil.endOfDay(new Date());
        long time2 = endTime.getTime();
        Instant instant2 = Instant.ofEpochMilli(time2);
        ZoneId zoneId2 = ZoneId.systemDefault();
        LocalDateTime localendTime2 = instant2.atZone(zoneId2).toLocalDateTime();

        return  reservationMapper.countCancelledReservationsWithinTimeRange(localStartTime,localendTime2,userId);
    }

    /**
     * 查询每个时间段剩余预约次数
     */
    @Override
    public List<TimeCountVo> countByTime(Long time) {
        // 根据当前时间获取当天最早时间
        DateTime startTime = DateUtil.beginOfDay(new Date(time));
        long sTime = startTime.getTime();
        Instant instant1 = Instant.ofEpochMilli(sTime);
        ZoneId zoneId1 = ZoneId.systemDefault();
        LocalDateTime start = instant1.atZone(zoneId1).toLocalDateTime();

        // 根据当前时间获取当天最晚时间
        DateTime endTime = DateUtil.endOfDay(new Date(time));
        long eTime = endTime.getTime();
        Instant instant2 = Instant.ofEpochMilli(eTime);
        ZoneId zoneId2 = ZoneId.systemDefault();
        LocalDateTime end = instant2.atZone(zoneId2).toLocalDateTime();

        return  reservationMapper.countReservationsByTimeRange(start, end);
    }

    /**
     *  新增预约
     */
    @Override
    public void addReservation(ReservationDto reservationDto) {
        Reservation reservation = BeanUtil.toBean(reservationDto, Reservation.class);
        String mobile = reservation.getMobile();
        if(StrUtil.isEmpty(mobile)){
            throw new BaseException(BasicEnum.PARAMETER_MISSING);
        }
        // 根据手机号查询用于预约信息
        LocalDateTime time = reservation.getTime();
        if(time == null){
            throw new BaseException(BasicEnum.PARAMETER_MISSING);
        }
        LocalDateTime startTime = LocalDateTimeUtil.beginOfDay(time);
        LocalDateTime endTime = LocalDateTimeUtil.endOfDay(time);
        // 获取这个手机号的当天预约总条数
        List<Reservation> all = reservationMapper.findAll(reservation.getCreateBy(), reservation.getMobile(), startTime, endTime);
        // 找出这个手机号当天取消的次数（2：取消）
        long cancelCount = all.stream().filter(item -> item.getStatus() == 2).count();
        // 1、如果当前预约用户手机号 , 当日预约取消数量超过三次则不能预约
        if(cancelCount > 3){
            throw new BaseException(BasicEnum.RESERVATION_CANCEL_COUNT_UPPER_LIMIT);
        }
        // 2、如果当前预约用户手机号下 , 当日存在 待报道(0) 或者 已完成的预约(1), 则不能再次预约
        long finishCount = all.stream().filter(item -> item.getStatus() == 0 || item.getStatus() == 1).count();
        if(finishCount > 0){
            throw new BaseException(BasicEnum.TIME_ALREADY_RESERVATED_BY_PHONE);
        }
        // 3、如果是探访预约 , 需要判断老人状态 , 如果老人不存在或者已退住则不能预约
        if(reservation.getType() == 1){
            Long elderId = reservation.getElderId();
            if(reservation.getElderId() == null){
                throw new BaseException(BasicEnum.ELDER_NOT_EXIST);
            }
            Elder elder = elderMapper.selectByPrimaryKey(elderId);
            if(elder.getStatus() == 5){
                throw new BaseException(BasicEnum.CANNOT_RESERVATION_DUE_ELDER_ALREADY_RETREATED);
            }
        }
        //可以预约
        reservation.setStatus(0);
        reservation.setUpdateTime(LocalDateTime.now());
        reservationMapper.insert(reservation);
    }

    /**
     *  分页查询预约
     */
    @Override
    public PageResponse<ReservationVo> findByPage2(Integer pageNum, Integer pageSize, Integer status) {
        PageHelper.startPage(pageNum,pageSize);
        Long userId = MobThreadLocal.getUserId();
        Page<Reservation> page2 = reservationMapper.findByPage2(userId,status);
        return PageResponse.of(page2,ReservationVo.class);
    }

    /**
     * 取消预约
     */
    @Override
    public void cancelReservation(Long id) {
        Reservation byId = reservationMapper.findById(id);
        if(byId == null){
            throw new BaseException(BasicEnum.PARAMETER_MISSING);
        }
        byId.setStatus(2);
        byId.setUpdateTime(LocalDateTime.now());
        reservationMapper.update(byId);
    }
}

